﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.ComponentModel;
using TED.Model;
using System.Windows.Threading;
using Microsoft.Phone.Shell;

namespace TED.ViewModels
{
    public class SearchViewModel
    {
        public delegate void RunElementDelegate(string parameter);
        private const int numberOfPages = 5;

        public class Search
        {
            private string _title;

            public string Title
            {
                get { return _title; }
                set { _title = value; }
            }
            private string _viewUrl;

            public string ViewUrl
            {
                get { return _viewUrl; }
                set { _viewUrl = value; }
            }

        };

        private string _searchString = "data";

        public string SearchString
        {
            get { return _searchString; }
            set { _searchString = value; }
        }

        private int _pivotIndex = 0;

        public int PivotIndex
        {
            get { return _pivotIndex; }
            set { _pivotIndex = value;
            this.NotifyPropertyChanged("PivotIndex");
            }
        }

        public class Job
        {
            public RunElementDelegate Function { get; set; }
            public string Parameter { get; set; }
        }

        public List<Job> ElementsToRun = new List<Job>();

        public int CurrentElementToRun = 0;
        public BackgroundWorker Worker;
        public int JobsCount
        {
            get { return ElementsToRun.Count; }
        }

        public delegate void ElementFinishedDelegate();
        public event ElementFinishedDelegate ElementFinished;

        public delegate void WorkFinishedDelegate(bool success);
        public event WorkFinishedDelegate WorkFinished;

        public SearchViewModel()
        {
            TalkSearchedItems = new ObservableCollection<TEDVideo>();
            Worker = new BackgroundWorker();
            Worker.WorkerSupportsCancellation = true;
            Worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
            this.ElementFinished += new ElementFinishedDelegate(SearchViewModel_ElementFinished);
        }

        void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (CurrentElementToRun < ElementsToRun.Count)
            {
                RunElementDelegate function = new RunElementDelegate(ElementsToRun[CurrentElementToRun].Function);
                function(ElementsToRun[CurrentElementToRun].Parameter);
            }
        }

        void SearchViewModel_ElementFinished()
        {
            CurrentElementToRun++;

            if (CurrentElementToRun > ElementsToRun.Count - 1)
            {
                Worker.CancelAsync();
                WorkFinished(true);
                return;
            }

            RunElementDelegate function = new RunElementDelegate(ElementsToRun[CurrentElementToRun].Function);
            function(ElementsToRun[CurrentElementToRun].Parameter);
        }

        //Parse www.ted.com/talks
        #region SearchViewModelTalks
        public void DoSearch()
        {
            this.CurrentElementToRun = 0;
            this.ElementsToRun = new List<Job>();

            // data visualization ==> data+visualization
            this.SearchString.Trim();
            this.SearchString.Replace(" ", "+");

            Job job = new Job();
            job.Function = SearchTEDTalks;
            job.Parameter = this.SearchString;
            this.ElementsToRun.Add(job);

            this.Worker.RunWorkerAsync();

        }

        /// <summary>
        /// Search TED website using a simpler method: WebClient
        /// </summary>
        /// <param name="i">the page number</param>
        public void SearchTEDTalks(string query)
        {
            WebClient c = new WebClient();
            string TEDUrl = "http://www.ted.com/search?q=" + query;
            c.DownloadStringAsync(new Uri(TEDUrl));
            c.DownloadStringCompleted += new DownloadStringCompletedEventHandler(c_DownloadStringCompleted);
        }

        /// <summary>
        /// Handle html that is returned from searching
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void c_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                Worker.CancelAsync();
                this.WorkFinished(false);
            }
            lock (this)
            {
                string responseString = e.Result;

                ParseHTML(responseString);
                ElementFinished();
            }

        }


        /// <summary>
        /// Parse HTML from searching result
        /// </summary>
        /// <param name="responseString">string returned from server</param>
        private void ParseHTML(string responseString)
        {
            ////Begin parsing code
            //int iFirst = responseString.IndexOf("<div class=\"talkListContainer");
            //int iLast = responseString.IndexOf("<div class=\"pagination clearfix\">");
            //int iLength = iLast - iFirst;
            //responseString = responseString.Substring(iFirst, iLength);

            //Replace "&amp" by "&"
            string oldChar = "&amp";
            responseString = responseString.Replace(oldChar, "&");
            Console.Write(responseString);

            // Now, parse html to get Title & URL of each Talk
            //string regexLinkPatter = @"<a.*?title=[""'](?<title>.*?)[""'].*?href=[""'](?<url>.*?)[""'].*?>.*?<img.*?<img.*?alt=[""'].*?[""'].*?src=[""'](?<imageUrl>.*?)[""'].*?/>";
            string noResultPattern = @"(No).(result).(matches).(your).(query).";
            MatchCollection noResultMatch = Regex.Matches(responseString, noResultPattern);

            if (noResultMatch.Count == 0)
            {
                string talkPattern = @"<dt><a.*?href=[""'](?<viewUrl>.*?)[""'].*?>(?<title>.*?)(Video).(on).TED.*?</a></dt>";
                MatchCollection talkMatches = Regex.Matches(responseString, talkPattern);

                string speakerPattern = @"<dt><a.*?href=[""'](?<viewUrl>.*?)[""'].*?>(?<title>.*?)(Profile).(on).(TED).*?</a></dt>";
                MatchCollection speakerMatches = Regex.Matches(responseString, speakerPattern);

                string[] talkmatchURL = new string[talkMatches.Count];
                string[] talkmatchTitle = new string[talkMatches.Count];

                foreach (System.Text.RegularExpressions.Match match in talkMatches)
                {
                    String description = match.Groups["title"].Value;
                    int indexOf = description.IndexOf("|");

                    TalkSearchedItems.Add(new TEDVideo
                    {
                        Title = (match.Groups["title"].Value.ToString()).Substring(0, indexOf),
                        ViewUrl = "/Video.xaml?url=" + match.Groups["viewUrl"].Value.Substring(15)
                    });
                }
                this.NotifyPropertyChanged("TalkSearchedItems");
            }
            else
                MessageBox.Show("No results matches your query");
        }
        #endregion

        //Collection

        #region TalkSearchedItems

        public ObservableCollection<TEDVideo> _TalkSearchedItems;
        public ObservableCollection<TEDVideo> TalkSearchedItems
        {
            get { return _TalkSearchedItems; }
            private set
            {
                if (TalkSearchedItems == value)
                {
                    return;
                }

                _TalkSearchedItems = value;

                this.NotifyPropertyChanged("TalkSearchedItems");
            }
        }
        #endregion

        #region SpeakerSearchedItems

        public ObservableCollection<TEDVideo> _SpeakerSearchedItems;
        public ObservableCollection<TEDVideo> SpeakerSearchedItems
        {
            get { return _SpeakerSearchedItems; }
            private set
            {
                if (SpeakerSearchedItems == value)
                {
                    return;
                }

                _SpeakerSearchedItems = value;

            }
        }
        #endregion

        // Utility

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}
